﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using System.Data.SqlClient;
using System.Data.EntityClient;
using VLUSM_DataAccess;
using VLUSM_BusinessLogic.Helpers;
using VLUSM_BusinessLogic.DataTransferObjects;
using System.Data;
using System.Collections.ObjectModel;

namespace VLUSM_BusinessLogic
{
    public class SystemManager
    {
        IUnityContainer container;

        EntityConnection mainDataConnection;
        EntityConnection DVHCConnection;
        EntityConnection diemConnection;

        #region Constructor
        public SystemManager(IUnityContainer container)
        {
            this.container = container;
            this.Initialize();
        }
        #endregion

        public ObservableCollection<DonViDTO> GetDonViList()
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.DonVi;
                var oc = new ObservableCollection<DonVi>(result);
                return Converter.ConvertToDonViDTOList(oc);
            }
        }

        #region User Methods
        public ObservableCollection<UserDTO> GetUserList()
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.User;
                var oc = new ObservableCollection<User>(result);
                return Converter.ConvertToUserDTOList(oc);
            }
        }

        public ObservableCollection<UserDTO> GetUserByDonViID(int DonViIDFilter)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.User;
                var oc = new ObservableCollection<User>(result);
                return Converter.ConvertToUserDTOList(oc);
            }
        }

        public UserDTO GetUserByID(int IDFilter)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.User.Single(u => u.ID == IDFilter);
                return Converter.ConvertToUserDTO(result);
            }
        }

        public UserDTO GetUserByTenTaiKhoan(string TenTaiKhoanFilter)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.User.Single(u => u.TenTaiKhoan == TenTaiKhoanFilter);
                return Converter.ConvertToUserDTO(result);
            }
        }

        public void SaveUser(UserDTO objdto)
        {
            var obj = Converter.ConvertToUser(objdto);
            using (var context = container.Resolve<MainDataContainer>())
            {
                context.User.Attach(obj);
                if (obj.ID != 0)
                {
                    context.ObjectStateManager.ChangeObjectState(obj, EntityState.Modified);
                }
                else
                {
                    obj.MatKhau = "vanlang";
                    context.ObjectStateManager.ChangeObjectState(obj, EntityState.Added);
                }
                context.SaveChanges();
            }
        }

        public void SaveUserWithDonViList(UserDTO objdto, ObservableCollection<DonViDTO> listdto)
        {
            objdto.MatKhau = "vanlang";
            objdto.IsLocked = false;
            var obj = Converter.ConvertToUser(objdto);
            var list = Converter.ConvertToDonViList(listdto);
            foreach (var donVi in list)
            {
                obj.DonVis.Add(donVi);
            }

            using (var context = container.Resolve<MainDataContainer>())
            {
                context.User.AddObject(obj);
                foreach (var donVi in obj.DonVis)
                {
                    context.ObjectStateManager.ChangeObjectState(donVi, EntityState.Unchanged);
                }
                context.SaveChanges();
            }
        }

        public void SaveDonViWithQuyenList(DonViDTO objdto, ObservableCollection<QuyenDTO> listdto)
        {
            var obj = Converter.ConvertToDonVi(objdto);
            var list = Converter.ConvertToQuyenList(listdto);
            foreach (var quyen in list)
            {
                obj.Quyens.Add(quyen);
            }

            using (var context = container.Resolve<MainDataContainer>())
            {
                context.DonVi.AddObject(obj);
                foreach (var quyen in obj.Quyens)
                {
                    context.ObjectStateManager.ChangeObjectState(quyen, EntityState.Unchanged);
                }
                context.SaveChanges();
            }
        }

        public ObservableCollection<DonViDTO> GetDonViNotYetByUserID(int UserID)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.DonVi.Where(d => !d.Users.Any(u => u.ID == UserID));
                var oc = new ObservableCollection<DonVi>(result);
                return Converter.ConvertToDonViDTOList(oc);
            }
        }

        public ObservableCollection<DonViDTO> GetDonViByUserID(int UserID)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.DonVi.Where(d => d.Users.Any(u => u.ID == UserID));
                var oc = new ObservableCollection<DonVi>(result);
                return Converter.ConvertToDonViDTOList(oc);
            }
        }

        public void SetDonViListForUser(int UserID, ObservableCollection<DonViDTO> listDTO)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var userQuery = context.User.Single(u => u.ID == UserID);
                var list = Converter.ConvertToDonViList(listDTO);
                foreach (var donvi in list)
                {
                    userQuery.DonVis.Add(donvi);
                }

                foreach (var donvi in userQuery.DonVis)
                {
                    context.ObjectStateManager.ChangeObjectState(donvi, EntityState.Unchanged);
                }
                context.SaveChanges();
            }
        }

        public void UnSetDonViListForUser(int UserID, ObservableCollection<DonViDTO> listDTO)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var userQuery = context.User.Single(d => d.ID == UserID);

                foreach (var donvidto in listDTO)
                {
                    var donvi = context.DonVi.FirstOrDefault(d => d.ID == donvidto.ID);
                    userQuery.DonVis.Attach(donvi);
                    userQuery.DonVis.Remove(donvi);
                }
                context.SaveChanges();
            }
        }

        public void RemoveUser(UserDTO objdto)
        {
            var obj = Converter.ConvertToUser(objdto);
            using (var context = container.Resolve<MainDataContainer>())
            {
                context.User.Attach(obj);
                context.ObjectStateManager.ChangeObjectState(obj, EntityState.Deleted);
                context.SaveChanges();
            }
        }

        public void RemoveUserByID(int IDFilter)
        {
            
            using (var context = container.Resolve<MainDataContainer>())
            {
                var obj = context.User.Single(h => h.ID == IDFilter);
                foreach (var donVi in obj.DonVis.ToList())
                {
                    obj.DonVis.Remove(donVi);
                }
                context.ObjectStateManager.ChangeObjectState(obj, EntityState.Deleted);
                context.SaveChanges();
            }
        }

        public void AssignUserToDonVi(int UserID, int DonViID)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var donViQuery = context.DonVi.Single(d => d.ID == DonViID);
                var userQuery = context.User.Single(u => u.ID == UserID);
                donViQuery.Users.Add(userQuery);
                context.SaveChanges();
            }
        }

        public void AssignUserListToDonVi(ObservableCollection<UserDTO> dtoList, int DonViID)
        {
            var list = Converter.ConvertToUserList(dtoList);
            using (var context = container.Resolve<MainDataContainer>())
            {
                var donViQuery = context.DonVi.Single(d => d.ID == DonViID);
                foreach (var user in list)
                {
                    donViQuery.Users.Add(user);
                }
                context.SaveChanges();
            }
        }
        #endregion

        #region Quyen Methods
        public ObservableCollection<QuyenDTO> GetQuyenList()
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.Quyen;
                var oc = new ObservableCollection<Quyen>(result);
                return Converter.ConvertToQuyenDTOList(oc);
            }
        }

        public ObservableCollection<QuyenDTO> GetQuyenByDonViID(int DonViIDFilter)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.Quyen.Where(q => q.DonVis.Any(d => d.ID == DonViIDFilter));
                var oc = new ObservableCollection<Quyen>(result);
                return Converter.ConvertToQuyenDTOList(oc);
            }
        }

        public ObservableCollection<QuyenDTO> GetQuyenNotYetByDonViID(int DonViIDFilter)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var result = context.Quyen.Where(q => !q.DonVis.Any(d => d.ID == DonViIDFilter));
                var oc = new ObservableCollection<Quyen>(result);
                return Converter.ConvertToQuyenDTOList(oc);
            }
        }

        public void SetQuyenForDonVi(int DonViID, int QuyenID)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var donViQuery = context.DonVi.Single(d => d.ID == DonViID);
                var quyenQuery = context.Quyen.Single(q => q.ID == QuyenID);
                if (!donViQuery.Quyens.Contains(quyenQuery))
                {
                    donViQuery.Quyens.Add(quyenQuery);
                }
                context.SaveChanges();
            }
        }

        public void SetQuyenListForDonVi(int DonViID, ObservableCollection<QuyenDTO> listDTO)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var donViQuery = context.DonVi.Single(d => d.ID == DonViID);
                var list = Converter.ConvertToQuyenList(listDTO);
                foreach (var quyen in list)
                {
                    donViQuery.Quyens.Add(quyen);
                }

                foreach (var quyen in donViQuery.Quyens)
                {
                    context.ObjectStateManager.ChangeObjectState(quyen, EntityState.Unchanged);
                }
                context.SaveChanges();
            }
        }

        public void UnSetQuyenListForDonVi(int DonViID, ObservableCollection<QuyenDTO> listDTO)
        {
            using (var context = container.Resolve<MainDataContainer>())
            {
                var donViQuery = context.DonVi.Single(d => d.ID == DonViID);

                foreach (var quyendto in listDTO)
                {
                    var quyen = context.Quyen.FirstOrDefault(q => q.ID == quyendto.ID);
                    donViQuery.Quyens.Attach(quyen);
                    donViQuery.Quyens.Remove(quyen);
                }
                context.SaveChanges();
            }
        }

        #endregion

        #region Private Methods
        private void Initialize()
        {
            DVHCConnection = EntityConnectionCreator.Instance.DonViHanhChinhConnection;
            mainDataConnection = EntityConnectionCreator.Instance.MainDataConnection;
            diemConnection = EntityConnectionCreator.Instance.DiemConnection;

            this.UnityRegisterType();
            this.InitializeMapper();
        }

        private void UnityRegisterType()
        {
            container.RegisterType<MainDataContainer>(new InjectionConstructor(mainDataConnection));
        }

        private void InitializeMapper()
        {
            Converter.ConfigureQuyenMapping();
            Converter.ConfigureUserMapping();
            Converter.ConfigureDonViMapping();
        }
        #endregion
    }
}
